package com.ethanhua.skeleton;

import io.supercharge.shimmerlayout.ShimmerLayout;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.LayoutScatter;
import ohos.global.resource.NotExistException;
import ohos.global.resource.WrongTypeException;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

import java.io.IOException;
import java.util.Collections;

/**
 * Created by ethanhua on 2017/7/29.
 *
 * @since 2021-04-16
 */
public class ViewSkeletonScreen implements SkeletonScreen {
    static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00201, "ViewSkeletonScreen");
    private final ViewReplacer mViewReplacer;
    private final ComponentContainer mActualView;
    private final int mSkeletonResId;
    private final int mShimmerColor;
    private final boolean isShimmer;
    private final int mShimmerDuration;
    private final int mShimmerAngle;
    private int mChildBackgroundColor;

    private ViewSkeletonScreen(Builder builder) {
        mActualView = builder.mView;
        mSkeletonResId = builder.mSkeletonLayoutResId;
        isShimmer = builder.isShimmer;
        mShimmerDuration = builder.mShimmerDuration;
        mShimmerAngle = builder.mShimmerAngle;
        mShimmerColor = builder.mShimmerColor;
        mChildBackgroundColor = builder.mChildBackgroundColor;
        mViewReplacer = new ViewReplacer(builder.mView);
    }

    private ShimmerLayout generateShimmerContainerLayout(ComponentContainer parentView) {
        final ShimmerLayout shimmerLayout = (ShimmerLayout) LayoutScatter.getInstance(
                mActualView.getContext()).parse(ResourceTable.Layout_layout_shimmer, parentView, false);
        shimmerLayout.setShimmerColor(mShimmerColor);
        shimmerLayout.setShimmerAngle(mShimmerAngle);
        shimmerLayout.setShimmerAnimationDuration(mShimmerDuration);
        shimmerLayout.setChildBackgroundColor(mChildBackgroundColor);
        ComponentContainer innerView = (ComponentContainer) LayoutScatter.getInstance(
                mActualView.getContext()).parse(mSkeletonResId, parentView, false);
        ComponentContainer.LayoutConfig lp = innerView.getLayoutConfig();
        shimmerLayout.setComponentContainer(innerView);
        if (lp != null) {
            shimmerLayout.setLayoutConfig(lp);
        }

        shimmerLayout.startShimmerAnimation();
        return shimmerLayout;
    }

    private Component generateSkeletonLoadingView() {
        if (mActualView == null) {
            HiLog.error(LABEL, "the source view have not attach to any view");
            return (Component)Collections.emptyList();
        }
        if (isShimmer) {
            return generateShimmerContainerLayout(mActualView);
        }
        return LayoutScatter.getInstance(mActualView.getContext()).parse(mSkeletonResId, mActualView, false);
    }

    @Override
    public void show() {
        Component skeletonLoadingView = generateSkeletonLoadingView();
        if (skeletonLoadingView != null) {
            mViewReplacer.replace(skeletonLoadingView);
        }
    }

    @Override
    public void hide() {
        mViewReplacer.restore();
    }

    /**
     * Builder
     *
     * @since 2021-04-16
     */
    public static class Builder {
        private static final int DURATION = 1000;
        private static final int ANGLE = 20;
        private final ComponentContainer mView;
        private int mSkeletonLayoutResId;
        private boolean isShimmer = true;
        private int mShimmerColor;
        private int mShimmerDuration = DURATION;
        private int mShimmerAngle = ANGLE;
        private int mChildBackgroundColor;

        /**
         * Builder
         *
         * @param view
         */
        public Builder(ComponentContainer view) {
            this.mView = view;
            ohos.global.resource.ResourceManager resManager = view.getContext().getResourceManager();
            try {
                this.mShimmerColor = resManager.getElement(ResourceTable.Color_shimmer_color).getColor();
                this.mChildBackgroundColor = resManager.getElement(ResourceTable.Color_background_color).getColor();
            } catch (IOException | WrongTypeException | NotExistException e) {
                HiLog.error(LABEL,"");
            }
        }

        /**
         * the loading skeleton layoutResID
         *
         * @param skeletonLayoutResId the loading skeleton layoutResID
         * @return ViewSkeletonScreen
         */
        public Builder load(int skeletonLayoutResId) {
            this.mSkeletonLayoutResId = skeletonLayoutResId;
            return this;
        }

        /**
         * the shimmerColor of the animation.
         *
         * @param shimmerColor the shimmer color
         * @return ViewSkeletonScreen
         */
        public Builder color(/*@ColorRes */int shimmerColor) {
            this.mShimmerColor = shimmerColor;
            return this;
        }

        /**
         * whether show shimmer animation
         *
         * @param isShimmerShow whether show shimmer animation
         * @return ViewSkeletonScreen
         */
        public Builder shimmer(boolean isShimmerShow) {
            this.isShimmer = isShimmerShow;
            return this;
        }

        /**
         * the duration of the animation , the time it will take for the highlight to move from one end of the layout
         * to the other.
         *
         * @param shimmerDuration Duration of the shimmer animation, in milliseconds
         * @return ViewSkeletonScreen
         */
        public Builder duration(int shimmerDuration) {
            this.mShimmerDuration = shimmerDuration;
            return this;
        }

        /**
         * the angle of the shimmer effect in clockwise direction in degrees.
         *
         * @param shimmerAngle the angle of the shimmer effect in clockwise direction in degrees.
         * @return ViewSkeletonScreen
         */
        public Builder angle(int shimmerAngle) {
            this.mShimmerAngle = shimmerAngle;
            return this;
        }

        /**
         * whether show background of childView
         *
         * @param backgroundColor whether show background of childView
         * @return ViewSkeletonScreen
         */
        public Builder childBackgroundColor(int backgroundColor) {
            this.mChildBackgroundColor = backgroundColor;
            return this;
        }

        /**
         * 显示骨架屏
         *
         * @return ViewSkeletonScreen
         */

        public ViewSkeletonScreen show() {
            ViewSkeletonScreen skeletonScreen = new ViewSkeletonScreen(this);
            skeletonScreen.show();
            return skeletonScreen;
        }
    }
}
